package com.letoken.platform.app.controller;

import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.letoken.platform.app.service.WalletTokenService;
import com.letoken.platform.pub.annotation.auth.NotAuthorization;
import com.letoken.platform.pub.annotation.pub.Trim;
import com.letoken.platform.pub.constant.ConstantsValue;
import com.letoken.platform.pub.constant.LetokenUserConstant;
import com.letoken.platform.pub.constant.RedisKeyConstant;
import com.letoken.platform.pub.enums.LetokenApiResponseEnum;
import com.letoken.platform.pub.enums.LetokenTokenTypeEnum;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.pub.req.token.TokenErc20TxReq;
import com.letoken.platform.pub.res.ApiResponse;
import com.letoken.platform.pub.res.token.TokenErc20TxRes;
import com.letoken.platform.pub.res.web3.MoralisTokenPrice;
import com.letoken.platform.pub.util.*;
import com.letoken.platform.repo.app.po.AppUserLoginLog;
import com.letoken.platform.pub.util.CoingeckoUtil;
import com.letoken.platform.pub.util.MD5Util;
import com.letoken.platform.pub.util.MoralisUtil;
import com.letoken.platform.repo.admin.dao.AdminCommunityConfigMapper;
import com.letoken.platform.repo.app.dao.AppWithdrawConfigMapper;
import com.letoken.platform.repo.app.manager.AppUserManager;
import com.letoken.platform.repo.app.po.AppUser;
import com.letoken.platform.repo.app.redis.AppJsonStringRedis;
import com.letoken.platform.repo.app.redis.AppTokenPriceRedis;
import com.letoken.platform.repo.app.redis.AppWalletRateLimitRedis;
import com.letoken.platform.repo.app.redis.RedisConfig;
import com.letoken.platform.repo.app.req.token.WithdrawUsdtReq;
import com.letoken.platform.repo.app.req.user.UserLevelReq;
import com.letoken.platform.repo.app.res.token.LetokenTokenPriceRes;
import com.letoken.platform.repo.utlis.WebUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.log4j.Log4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author letokenlabs
 * @date 2022/12/3$
 */
@RestController
@RequestMapping("/token")
@Api(tags = "Le账户-代币")
public class AppTokenController {

//    @Autowired
//    private WalletMQManager walletMQManager;

//    @Autowired
//    private RabbitTemplate rabbitTemplate;
    @Autowired
    private WalletTokenService walletTokenService;

    @Resource
    private RedisConfig redisConfig;

    @Autowired
    private HttpServletRequest request;


    /*@Resource
    AdminCommunityConfigMapper adminCommunityConfigMapper;
    @Resource
    AppWithdrawConfigMapper appWithdrawConfigMapper;

    @Autowired
    AppUserManager appUserManager;*/

//    @Trim
//    @SysLog(description = "充值回调", operationType = LogOperationType.UNKNOWN, operationModule = LogOperationModule.UNKNOWN,
//            coreFields = {"login"})
//    @PostMapping("/recharge/callback")
//    @ApiOperation(value = "充值-USDT充值回调", notes = "usdt充值回调")
//    public ApiResponse rechargeCallback(@RequestBody @Validated RechargeCallbackReq req) {
//        // walletMQManager.rechargeConfirm(rabbitTemplate, req, 3000 * 2);
//        return ApiResponse.create();
//    }

    @Trim
    @PostMapping("/withdraw")
    @ApiOperation(value = "提现", notes = "提现-USDT")
    public ApiResponse tokenWithdraw(@Validated @RequestBody WithdrawUsdtReq req) {
//        Withdraw withdraw = walletTokenService.tokenWithdraw(req);
//        if (withdraw != null){
//            withdraw.insert();
//            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_WALLET_WITHDRAW_017);
//        }

      //  check(appUserManager.queryMe());

        if (ObjectUtils.isEmpty(req.getTokenId())){
            req.setTokenId(LetokenTokenTypeEnum.USDT.getId());
        }

        if(1 == req.getTokenId()){
            req.setTokenId(2);
        }
        if (!LetokenTokenTypeEnum.LET.getId().equals(req.getTokenId())
                && !LetokenTokenTypeEnum.CAP.getId().equals(req.getTokenId())
                && !LetokenTokenTypeEnum.CAPA.getId().equals(req.getTokenId())
                && !LetokenTokenTypeEnum.LP.getId().equals(req.getTokenId())){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_058);
        }

        String key = String.format(RedisKeyConstant.UPDATE_WALLET_INFO,WebUtils.getUserId());
        RedissonClient redissonClient = redisConfig.getRedisson();
        RLock rlock = redissonClient.getLock(key);
        try {
            rlock.lock(15, TimeUnit.SECONDS);
            walletTokenService.tokenWithdrawNew(req);
        }finally {
            if (rlock != null && rlock.isHeldByCurrentThread()) {
                rlock.unlock();
            }
        }

        return ApiResponse.create();
    }

   /* private void check(AppUser appUser){
        Integer level = appWithdrawConfigMapper.getLevel(appUser.getId());
        List<Integer> list1 = appWithdrawConfigMapper.getListUserId();
        if(level.equals(2) && !list1.contains(appUser.getId()))throw new RuntimeException("提现异常!!!");

        if(!level.equals(2)){
            if(appUser.getInviterId()==null)throw new RuntimeException("提现异常!!!");

            List<UserLevelReq> list = adminCommunityConfigMapper.selectUserLevelCommunityBywithdraw(appUser.getId());
            if (list == null || list.size() ==0)throw new RuntimeException("提现异常!!!");

            if(!list1.contains(list.get(0).getUserId()))throw new RuntimeException("提现异常!!!");
        }
    }*/

    @NotAuthorization
    @GetMapping("token/prices")
    @ApiOperation(value = "获取代币价格", notes = "获取代币价格")
    public ApiResponse<List<LetokenTokenPriceRes>> querySystemTokenPrice(
            @ApiParam(name = "netType", value = "bsc") @RequestParam String netType
    ) {
        List<LetokenTokenPriceRes> list = walletTokenService.querySystemTokenPrice(netType);
        return ApiResponse.create(list);
    }

    @Trim
    @NotAuthorization
    @PostMapping("/tx/token")
    @ApiOperation(value = "Token-交易记录", notes = "Token-交易记录")
    public ApiResponse<List<TokenErc20TxRes>> queryWalletErc20Tx(@RequestBody @Validated TokenErc20TxReq req) {

        String key = MD5Util.MD5(JSON.toJSONString(req));
        if (!AppWalletRateLimitRedis.me().isLimited(key,"gettx", 1)) {

            if (StringUtils.isEmpty(req.getTokenAddress())) {
                return ApiResponse.create(walletTokenService.queryWalletTx(req));
            } else {
                return ApiResponse.create(walletTokenService.queryWalletErc20Tx(req));
            }
        }
        return ApiResponse.create(null);
    }

    @Trim
    @NotAuthorization
    @GetMapping("prices/erc20")
    @ApiOperation(value = "获取ERC20代币价格", notes = "获取ERC20代币价格")
    public ApiResponse<List<MoralisTokenPrice>> queryErc20TokenPrices(
            @ApiParam(name = "netType", value = "bsc") @RequestParam String netType,
            @ApiParam(name = "address", value = "0xaaa...,0xbbb...") @RequestParam String address
    ) {

        List<MoralisTokenPrice> data = null;

        String key1 = MD5Util.MD5(netType + address);
        String key = "letoken:cache:price:" + key1;
        String rs = AppJsonStringRedis.me().get(key);
        if (StringUtils.isEmpty(rs)) {

            List<MoralisTokenPrice> prices = new ArrayList<>();
            for (String token : address.split(",")) {
                if (!StringUtils.isEmpty(token)) {
                    MoralisTokenPrice item = MoralisUtil.getTokenPrice(netType, token);
                    if (item != null) {
                        prices.add(item);
                    }
                }
            }

            if (prices.size() > 0) {
                data = prices;
                rs = JSON.toJSONString(prices);
                AppJsonStringRedis.me().setValue(key, rs, 60 * 5); //5分钟
            }
        } else {
            data = com.alibaba.fastjson.JSONObject.parseArray(rs, MoralisTokenPrice.class);
        }
        return ApiResponse.create(data);
    }

    @Trim
    @NotAuthorization
    @GetMapping("prices/ids")
    @ApiOperation(value = "获取Coingecko代币价格", notes = "获取Coingecko代币价格")
    public ApiResponse<JSONObject> queryTokenPricesByIds(
            @ApiParam(name = "ids", value = "coingecko ids") @RequestParam String ids,
            @ApiParam(name = "vs_currencies", value = "usd,cny") @RequestParam String vs_currencies
    ) {
        String key = MD5Util.MD5(ids + vs_currencies);
        String rs = AppTokenPriceRedis.me().getValue(key);
        if (StringUtils.isEmpty(rs)) {
            com.alibaba.fastjson.JSONObject data = CoingeckoUtil.getTokenPrice(ids, vs_currencies);
            if (data != null) {
                rs = JSON.toJSONString(data);
                AppTokenPriceRedis.me().setValue(key, rs, 60 * 5); //5分钟
            }
        }

        return ApiResponse.create(StringUtils.isEmpty(rs) ? null : com.alibaba.fastjson.JSONObject.parse(rs));
    }
}
